package com.muchenxinxi.androidbaseapp.base;

import android.app.Application;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.os.Build;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.cache.CacheMode;
import com.lzy.okgo.cookie.store.PersistentCookieStore;
import com.muchenxinxi.androidbaseapp.BuildConfig;
import com.muchenxinxi.androidbaseapp.utils.AppUtils;
import com.muchenxinxi.androidbaseapp.utils.LogUtils;
import com.orhanobut.logger.LogLevel;
import com.orhanobut.logger.Logger;
import com.squareup.leakcanary.LeakCanary;

import java.util.logging.Level;

import me.drakeet.library.CrashWoodpecker;
import me.drakeet.library.PatchMode;

/**
 * ┏--------------------
 * │        /) /)
 * │     ฅ(• ﻌ •)ฅ
 * │  Created by HaoKing on 2017/2/23.
 * │  www.muchenxinxi.com
 * │  www.nextdever.com
 * │  QQ:773693552
 * │  QQ群: Geek Chat 344386592
 * ┗--------------------
 */

public class BaseApplication extends Application {

    //将该变量私有化，不允许外界修改，只提供一个getter方法
    //初始化在onCreate()中，方式比在gradle中配置要好
    private static boolean mIsDebugMode = false;

    public Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
        mIsDebugMode = AppUtils.isDebugMode(mContext);
        initApplication();
        //根据是否是调试运行模式进行不同的设置
        if (mIsDebugMode)
            initOnDebugMode();
        else
            initOnReleaseMode();

        //TODO 发布时启用下面的防破解检查，增加破解的难度
//        checkDebug();//反动态调试
//        checkIsRunAtEmulator();//反模拟器运行
    }

    private void initApplication() {
        //TODO 全局异常信息捕捉自定义处理，可选用
//        CrashCatcher.getInstance().init(mContext);
//        CrashCatcher.getInstance().init(mContext).setOnCrashCatchListener(this);

        //TODO 异常信息接收器，可选用
        CrashWoodpecker.instance()
                .withKeys("com.muchenxinxi")//默认为包名
                .setPatchMode(PatchMode.SHOW_LOG_PAGE)
                .setPatchDialogUrlToOpen("http://www.nextdever.com")
                .setPassToOriginalDefaultHandler(true)
                .flyTo(this);

        //内存泄漏检查
        LeakCanary.install(this);

        //OkGo网络请求框架初始化
        OkGo.init(this);
        OkGo.getInstance()
                // 打开该调试开关,打印级别INFO
                // 最后的true表示是否打印okgo的内部异常
                .debug("HaoKing", isDebugMode() ? Level.INFO : Level.OFF, isDebugMode())
                //全局统一设置超时重连次数,默认为三次
                .setRetryCount(3)
                //cookie持久化存储，如果cookie不过期，则一直有效
                .setCookieStore(new PersistentCookieStore())
                //请求网络失败后读取缓存
                .setCacheMode(CacheMode.REQUEST_FAILED_READ_CACHE)
                //可以设置https的证书,以下几种方案根据需要自己设置
                //方法一：自定义信任规则，校验服务端证书
                //.setCertificates(new SafeTrustManager())
                //方法二：使用预埋证书，校验服务端证书（自签名证书）
                //.setCertificates(getAssets().open("srca.cer"))
                //方法三：使用bks证书和密码管理客户端证书（双向认证），使用预埋证书，校验服务端证书（自签名证书）
                //.setCertificates(getAssets().open("xxx.bks"), "123456", getAssets().open("yyy.cer"))
                //方法四：信任所有证书,不安全有风险
                .setCertificates();

        //Fresco图片缓存加载框架初始化
        Fresco.initialize(this);
    }

    public void initOnReleaseMode() {
        checkDebug();//反动态调试
        checkIsRunAtEmulator();//反模拟器运行
        //可选 格式化日志输出功能 或者 简单的使用utils包里的 LogUtils 也可
        Logger.init("HaoKing").logLevel(LogLevel.NONE);
        LogUtils.LEVEL = LogUtils.NOTHING;
    }

    public void initOnDebugMode() {
        //可选 格式化日志输出功能 或者 简单的使用utils包里的 LogUtils 也可
        Logger.init("HaoKing").logLevel(LogLevel.FULL);
        LogUtils.LEVEL = LogUtils.VERBOSE;
    }

    public void checkDebug() {
        if ((getApplicationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE) != 0)
            android.os.Process.killProcess(android.os.Process.myPid());
    }

    public void checkIsRunAtEmulator() {
        //只要是在模拟器中，不管是什么版本的模拟器，在它的MODEL信息里就会带有关键字参数sdk
        if (Build.MODEL.contains("sdk") || Build.MODEL.contains("SDK"))
            android.os.Process.killProcess(android.os.Process.myPid());
    }

    public static boolean isDebugMode() {
        return mIsDebugMode;
    }
}
